#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <types.h>
#include <config.h>
#include <systems.h>

/* Unicode to unicode version strdup() */
unicode_t *uni_strdup(unicode_t *str)
{
    unicode_t *rstr;
    int len;
    
    if(!str)
        return NULL;
    
    len = uni_strlen(str);
    
    rstr = (unicode_t *)malloc(sizeof(unicode_t) * (len + 1));
    if(!rstr)
        return NULL;
        
    rstr = wcsncpy(rstr, str, len + 1);
    
    return rstr;
}

unicode_t *uni_ltow(long value, unicode_t *string, int radix)
{
    unsigned long val;
    int negative;
    unicode_t buffer[33];
    unicode_t *pos;
    unicode_t digit;

    if (value < 0 && radix == 10) {
    negative = 1;
        val = -value;
    } else {
    negative = 0;
        val = value;
    }

    pos = &buffer[32];
    *pos = '\0';

    do {
        digit = val % radix;
        val = val / radix;
        if (digit < 10) {
            *--pos = '0' + digit;
        } else {
            *--pos = 'a' + digit - 10;
        }
    } while (val != 0L);

    if (negative) {
        *--pos = '-';
    }

    if (string != NULL) {
        memcpy(string, pos, (&buffer[32] - pos + 1) * sizeof(unicode_t));
    }
    return string;
}

long uni_stol(const unicode_t *cp, unicode_t **endp, int base)
{
    long result = 0,value;
    int sign = 1;

    if ( *cp == L'-' ) {
        sign = -1;
        cp++;
    }

    if (!base) {
        base = 10;
        if (*cp == L'0') {
            base = 8;
            cp++;
            if ((*cp == L'x') && iswxdigit(cp[1])) {
                cp++;
                base = 16;
            }
        }
    }
    
    while (iswxdigit(*cp) && (value = iswdigit(*cp) ? *cp-L'0' : (iswlower(*cp)
            ? towupper(*cp) : *cp)-L'A'+10) < base) {
        result = result*base + value;
        cp++;
    }
    
    if (endp)
        *endp = (unicode_t *)cp;
        
    return result * sign;
}

unicode_t *uni_scat(unicode_t * __restrict s1, const unicode_t * __restrict s2)
{
    unicode_t *cp;

    cp = s1;
    while (*cp != L'\0')
        cp++;
    while ((*cp++ = *s2++) != L'\0');

    return s1;
}

int uni_strlen(const unicode_t * s)
{
    const unicode_t *save;

    if (s == 0)
        return 0;
    for (save = s; *save; ++save);
    return save-s;
}
